Lambda-backed カスタムリソースを理解するためにチュートリアルをやってみた
CloudFormationでリソースを定義する際、対応していないリソースがあったりパラメータではなく自動で値を取得したいと考えたことはないでしょうか?
そんなときに柔軟に対応してくれるのがカスタムリソースと呼ばれる定義方法です。
これまではカスタムリソースは使わずにCloudFormationテンプレートを利用していましたが、ついに使う機会がきたのでチュートリアルで理解を深めていこうと思います。
カスタムリソースには紐づけるリソースとしてSNSとLambdaの2種類がありますが、今回はLambdaを使ったLambda-backed カスタムリソース
を使っていきます。
やってみる
それでは早速チュートリアルをやっていきます。今回実施するのはAMIのIDを自動取得するLambdaをカスタムリソースとして作成して、取得したAMI IDからEC2インスタンスを起動するというものです。
チュートリアル: Amazon マシンイメージ ID を参照する
チュートリアルで実施するイメージとしては、CloudFormationテンプレート内で以下のようなことを実行します。
- S3からLambdaのコードを取得
- カスタムリソース
Custom::AMIInfo
からLambdaを実行 - LambdaからAMI IDをレスポンスとして返す
- 取得したAMI IDをEC2が参照し起動
ステップ 1: サンプルパッケージをダウンロードして Amazon S3 に保存する
サンプルとしてLambda関数を作成するためのパッケージをダウンロードします。WindouwとLinuxを選べるのですが、今回はLinux AMI の ID の検索するパッケージを以下からダウンロードしました。
https://s3.amazonaws.com/cloudformation-examples/lambda/amilookup.zip
次にS3バケットを作成します。バケット名はお好きなもので大丈夫です。リージョンはスタックを作成する予定のリージョンに作成するようにしてください。
その他の設定はデフォルトで作成して、先ほどダウンロードしたサンプルのzipファイルをアップロードします。
ここでアップロードしたファイルをCloudFormationテンプレートから呼び出して利用していきます。
ステップ 2: スタックを作成する
以下からスタック作成用のテンプレートをダウンロードします。
https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample.template
テンプレートの確認
そのままテンプレートからスタックを作成する前にテンプレートを理解しておきます。ダウンロードできるテンプレートはjsonですが、分かりにくいのでyamlに変換して確認しています。
AMIInfoFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref "S3Bucket" S3Key: !Ref "S3Key" Handler: !Join - "" - - !Ref "ModuleName" - .handler Role: !GetAtt "LambdaExecutionRole.Arn" Runtime: nodejs12.x Timeout: "30"
Lambdaが定義されているところを抜粋しています。先ほどアップロードしたS3バケットがCodeプロパティの!Ref "S3Bucket"
で定義されていることが確認できます。
次にカスタムリソースの定義されているところはType:Custom::AMIInfo
です。カスタムリソースの場合はTypeでCustom
と定義する必要があるので覚えておきましょう。
AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt "AMIInfoFunction.Arn" Region: !Ref "AWS::Region" Architecture: !FindInMap - AWSInstanceType2Arch - !Ref "InstanceType" - Arch
ServiceToken
ではLambdaのArnを取得していて、CloudFormationによってLambdaが呼び出されます。このLambdaが呼び出されると、Lambda関数がEC2 DescribeImages APIを呼び出し、最新のAMI IDを返してくれます。
返してくれるAMI IDの形は以下の通りです。
"Data": { "Id": "ami-43795473" }
上記のレスポンスを取得するときにはFn::GetAtt
を使います。レスポンスを取得しているのがSampleInstance
の部分です。
SampleInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !GetAtt AMIInfo.Id
AMIInfo
のIdを取得するとカスタムリソースのレスポンスで取得したAMI IDを自動で設定することができます。
スタックの作成
テンプレートを確認したところで、スタックを作成していきましょう。S3バケットと同じリージョンにすることを忘れないようにしてください。
スタックの作成からテンプレートにS3のURLを指定します。S3のURLは以下を利用してください。
https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample.template
スタック名にSampleEC2Instance
を入力し、S3Bucketにはステップ1で作成したバケット名を入力してください。
その他の値についてはデフォルトのまま作成します。スタックの作成が完了したら、出力タブにAMI IDが確認できます。
ステップ 3: リソースをクリーンアップする
お金がかからないようクリーンアップを忘れずに。料金は起動したEC2にかかるので作成したスタックを削除してください。作成したS3バケットも不要な場合は削除しておきましょう。
まとめ
チュートリアルを通してLambda-backed カスタムリソースを試してみました。意外とテンプレートの定義自体はそこまで難しくないので、Lambdaのコードをどう記述してレスポンスを返すかを考えれば活用できそうですね。
まだカスタムリソースが難しそうだと思っている人はこのチュートリアルからカスタムリソースを体験してみてはいかがでしょうか?